%%%====================================================================
%%% File    : pipe_join_lookup_mad.erl
%%% Author  :  <vjache>
%%% Description: This is a simpliest pipe implementation. It may be 
%%%				 considered as a simple reference implementation of 
%%%				 a pipe callback module, and could be used for debug 
%%%				 purposes.
%%%
%%% Created : 24.03.2009
%%%====================================================================

-module(pipe_join_lookup_mad).

%%
%% Include files
%%
-include("../include/pipe.hrl").
-include("../include/util.hrl").
%%
%% Exported Functions
%%
-export([
		 new/2,
		 new/5,
		 open/1,
		 push/2,
		 flush/1,
		 close/1,
		 test/1,
		 test/2]).

%%====================================================================
%% API Functions
%%====================================================================

new(LookupFunList,NextPipe) ->
	pipe:pipe_from_module(?MODULE, {LookupFunList,10,tup,[]}, NextPipe).
new(LookupFunList,BuffCap,Kind,Tag,NextPipe) ->
	pipe:pipe_from_module(?MODULE, {LookupFunList,BuffCap,Kind,[Tag]}, NextPipe).

open({{LookupFunList,BuffCap,Kind,TagL},NextPipe}) when BuffCap>1 -> %%PipeState
	%{_PToolDescr,_FoldFun,_FinishFun,_Acc0}
	PToolArgs={ptool_local:new(),
			   case TagL of %fold fun choice
				   [] ->
					   case Kind of
						   ls ->
							   
							   fun(_Key,Item,AccIn)->
									   [iter_join_lookup:new_flat_ls(iter:single(Item), LookupFunList)|AccIn]
							   end;
						   tup ->
							   fun(_Key,Item,AccIn)->
									   [iter_join_lookup:new_flat_tup(iter:single(Item), LookupFunList)|AccIn]
							   end
					   end;
				   [Tag] ->
					   case Kind of
						   ls ->
							   
							   fun(_Key,Item,AccIn)->
									   [iter_join_lookup:new_flat_ls(iter:single(Item), LookupFunList,Tag)|AccIn]
							   end;
						   tup ->
							   fun(_Key,Item,AccIn)->
									   [iter_join_lookup:new_flat_tup(iter:single(Item), LookupFunList,Tag)|AccIn]
							   end
					   end
			   end
			   ,
			   fun(_Key,AccTot)->%Finish fun (when flush occurs)
					   iter_concat:new(AccTot)
			   end,[]},
	{_PKFState=pipe:open(
				 ptool_pipe_keyfold:new(
				   PToolArgs, 
				   pipe_iter:new(NextPipe))),
	 _CountDown=BuffCap,
	 BuffCap}.
push({_PKFState,0,_BuffCap}=S,Item) ->
	push(flush(S),Item);
push({PKFState,CountDown,BuffCap},Item) ->
	PKFStateNew=pipe:push(PKFState,Item),
	{PKFStateNew,CountDown-1,BuffCap}.
flush({PKFState,_CountDown,BuffCap}=_S) ->
	{pipe:flush(PKFState),BuffCap,BuffCap}.
close({PKFState,_CountDown,_BuffCap}) ->
	ok=pipe:close(PKFState).

%%====================================================================
%% Test Functions
%%====================================================================

test(KeyList) ->
	D1=dict:from_list([
	 {k1,val1},
	 {k2,val2},
	 {k3,val3}
	 ]),
	D2=dict:from_list([
	 {k1,val21},
	 {k2,val22},
	 {k3,val23},
	 {k4,val24}
	 ]),
	S=pipe:open(new([
					 fun(K)->
						dict_lookup(K,D1)
					 end,
					 fun(K)->
						dict_lookup(K,D2)
					 end,
					 fun(K)->
						dict_lookup(K,D2)
					 end
					 ],pipe_console:new())),
	{IterState,PipeState}=pipe:push_each(S, iter:from_list(KeyList)),
	iter:close(IterState),
	pipe:close(PipeState).
test(ets,KeyList) ->
	Tid1=ets:new(a, [bag]),
	Tid2=ets:new(b, [bag]),
	Tid3=ets:new(c, [bag]),
	ets:insert(Tid1,[
	 {k1,val1},
	 {k2,val2},
	 {k3,val3},
	 {k6,val6}
	 ]),
	ets:insert(Tid2,[
	 {k1,val21},
	 {k2,val22},
	 {k3,val23},
	 {k4,val24},
	 {k6,val26}
	 ]),
	ets:insert(Tid3,[
	 {k0,val30},
	 {k2,val32},
	 {k3,val33},
	 {k4,val34},
	 {k5,val35},
	 {k6,val361},
	 {k6,val362},
	 {k6,val363},
	 {k6,val364},
	 {k6,val365},
	 {k6,val366},
	 {k6,val367},
	 {k6,val368}
	 ]),
	S=pipe:open(new([
					 fun(K)->
						ets_lookup(K,Tid1)
					 end,
					 fun(K)->
						ets_lookup(K,Tid2)
					 end,
					 fun(K)->
						ets_lookup(K,Tid3)
					 end
					 ],100,tup,result,pipe_console:new())),
	{IterState,PipeState}=pipe:push_each(S, iter:from_list(KeyList)),
	iter:close(IterState),
	pipe:close(PipeState).

dict_lookup(K,Dict)->
	L=case dict:find(K, Dict) of
		  error ->
			  [];
		  {ok,V} ->
			  [V]
	  end,
	iter:from_list(L).
ets_lookup(K,Tid)->
	iter_on_empty:new(iter:from_list(ets:lookup(Tid, K)),iter:single('$NULL')).
%%====================================================================
%% Local Functions
%%====================================================================

